﻿
Date.prototype.format = function (formatter) {
    return moment.tz(this, _config_.format.default.timezone).format(formatter);
};

Date.isLeapYear = function (year) {
    return (((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0));
};

Date.getDaysInMonth = function (year, month) {
    return [31, (Date.isLeapYear(year) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month];
};

Date.prototype.isLeapYear = function () {
    var y = this.getFullYear();
    return (((y % 4 === 0) && (y % 100 !== 0)) || (y % 400 === 0));
};

Date.prototype.getDaysInMonth = function () {
    return Date.getDaysInMonth(this.getFullYear(), this.getMonth());
};

Date.prototype.addMonths = function (value) {
    var n = this.getDate();
    this.setDate(1);
    this.setMonth(this.getMonth() + value);
    this.setDate(Math.min(n, this.getDaysInMonth()));
    return this;
};

String.prototype.endsWith = function (suffix) {
    return this.indexOf(suffix, this.length - suffix.length) !== -1;
};
String.prototype.trim = function () {
    return this.replace(/(^\s*)|(\s*$)/g, "");
};

String.prototype.getNumber = function () {
    if (this === "" || this === null || this === undefined) {
        return 0;
    }
    return numeral().unformat(this);
};

String.prototype.formatMonery = function (formatType) {
    if (!formatType) {
        formatType = '0,0.00';
    }
    return numeral(this).format(formatType);
};
String.prototype.formatMileage = function (formatType) {
    if (!formatType) {
        formatType = '0,0.0';
    }
    return numeral(this).format(formatType);
};


/*
* string extensions start
*/

/*
* 判断字符串是否包含value值
* @param { value } 任意字符串
* @returns bool 返回判断结果
*/
String.prototype.contains = function (value) {
    return this.indexOf(value) >= 0;
};

/*
* 判断字符串是否起始于value值
* @param { value } 任意字符串
* @returns bool 返回判断结果
*/
String.prototype.startWith = function (value) {
    return this.slice(0, value.length) === value;
};

/*
* 判断字符串是否结束于value值
* @param { value } 任意字符串
* @returns bool 返回判断结果
*/
String.prototype.endWith = function (value) {
    return this.indexOf(value, this.length - value.length) !== -1;
};

/*
* 字符串左填充, 当字符串长度低于 length 值时, 左边使用 char 来填充
* @param { length } 返回的字符串总长度
* @param { char } 填充字符
* @returns String 返回填充后的结果
*/
String.prototype.padLeft = function (length, char) {
    if ($.isNumeric(length) && length > this.length) {
        char = (typeof char === 'string' && char.length === 1) ? char : '0';
        var that = this;
        while (length > that.length) {
            that = char + that;
        }
        return that;
    }

    return this.toString();
};

/*
* 字符串右填充, 当字符串长度低于 length 值时, 右边使用 char 来填充
* @param { length } 返回的字符串总长度
* @param { char } 填充字符
* @returns String 返回填充后的结果
*/
String.prototype.padRight = function (length, char) {
    if ($.isNumeric(length) && length > this.length) {
        char = (typeof char === 'string' && char.length === 1) ? char : '0';
        var that = this;
        while (length > that.length) {
            that += char;
        }
        return that;
    }

    return this.toString();
};

/*
* 字符串两端去空格, 使用正则表达式实现
* @returns String 返回去空格后字符串
*/
String.prototype.trim = function () {
    return this.replace(/(^\s*)|(\s*$)/g, '');
};

String.prototype.hashCode = function () {
    var hash = 0, i, chr;
    if (this.length === 0) return hash;
    for (i = 0; i < this.length; i++) {
        chr = this.charCodeAt(i);
        hash = (hash << 5) - hash + chr;
        hash |= 0; // Convert to 32bit integer
    }
    return hash;
};


/*
* object array extensions start
*/

// get the all matched object of data object array, 
// callback is reference of filter function
Array.prototype.where = function (callback) {
    if (this.length !== 0 && $.isFunction(callback)) {
        return $.grep(this, callback);
    }
    return this;
};

// get the key's value array of the object data array, default key is "Name" 
// callback is reference of filter function
Array.prototype.select = function (key, callback) {
    key = key || 'Name';
    var data = this.where(callback);
    if ($.isArray(data) && data.length !== 0) {
        var array = [];
        var cur;
        $.each(data, function () {
            cur = $.com.getValue(this, key);
            if ($.com.hasValue(cur)) {
                array.push(cur);
            }
        });
        return array;
    }
    return undefined;
};

// get the first object of data object array, 
// callback is reference of filter function
Array.prototype.first = function (callback) {
    var data = this.where(callback);
    if ($.isArray(data) && data.length !== 0) {
        return data[0];
    }
    return undefined;
};

// whether callback condition object contains in data object array, 
// callback is reference of filter function
Array.prototype.exist = function (callback) {
    return this.first(callback) !== undefined;
};

//get the first object from a data array, and select the key value
Array.prototype.firstValue = function (callback, field) {
    field = field || "Name";
    var first = this.first(callback);
    if (typeof first !== 'undefined') {
        return first[field];
    }
    return undefined;
};

// distinct function of object data array
// keys is array of distinct field
Array.prototype.distinct = function (key) {
    var data = this;
    var arr = [];
    if (data.length !== 0) {
        var keys = key;
        keys = (keys || 'Name').split(',');
        for (var i = data.length; i > 0; i--) {
            var exist = true;
            var x = data[i - 1];
            //if current is string value, then ignore the keys
            if (typeof x === 'object') {
                $.each(keys, function (j, y) {
                    exist = exist && arr.exist(function (z) {
                        return z[y] === x[y];
                    });
                });
            } else {
                exist = arr.exist(function (y) {
                    return y === x;
                });
            }

            if (!exist) {
                arr.push(x);
            }
        }
    }

    return arr;
};

// insert item into array index position
Array.prototype.insert = function (item, index) {
    index = index || 0;
    this.splice(index, 0, item);
};

Array.prototype.sum = function () {
    return this.reduce(function (partial, value) {
        return partial + value;
    })
};

// insert item into array index position
Array.prototype.remove = function (item, key) {
    var keys = key;
    keys = (keys || 'Name').split(',');
    var index = -1;
    for (var i = 0; i < this.length; i++) {
        if (typeof item === 'object') {
            var match = true;
            for (var j = 0; j < keys.length; j++) {
                match = match && this[i][keys[j]] === item[keys[j]];
            }

            if (match) {
                index = i;
                break;
            }
        } else {
            if (this[i] === item) {
                index = i;
                break;
            }
        }
    }

    return this.splice(index, 1);
};

// array to map
Array.prototype.toMap = function (key, value) {
    if (this.length > 0) {
        var map = new Map();
        key = key || 'key';
        value = value || 'value';
        if (!this[0][key] && this[0][key] !== 0) {
            throw new Error('the key is not exist!');
        }

        for (var i = 0; i < this.length; i++) {
            map.set(this[i][key], this[i][value]);
        }

        return map;
    }
};

// map to array
Map.prototype.toArray = function () {
    if (this.size > 0) {
        var arr = [];
        this.forEach(function (value, key) {
            arr.push({ key: key, value: value });
        });

        return arr;
    }
};

// map to object
Map.prototype.toObject = function () {
    if (this.size > 0) {
        var obj = {};
        this.forEach(function (value, key) {
            obj[key] = value;
        });

        return obj;
    }
};


/*
* jQuery 扩展方法, 返回 el 在当前 jQuery 对象中的序号
* @param { el } 任意 jQuery 对象或选择器
* @returns 返回 el 在当前 jQuery 对象中的序号
*/
jQuery.fn.getIndex = function (el) {
    var $el = $(el);

    if (this.hasValue()) {
        var index = 0;
        for (var i = 0; i < this.length; i++) {
            if (this.eq(i).equal($el)) {
                index = i;
                break;
            }
        }

        return index;
    }

    return -1;
};

/*
* jQuery 扩展方法, 判断一个元素的 attr 属性是否为 true
* @param { attr } 当前元素上的属性名称
* @returns bool 返回判断结果
*/
jQuery.fn.isTrue = function (attr) {
    var result = false;
    var value = $.com.hasValue(attr) ? (this.attr(attr) || this.attr('data-' + attr)) : (this.val() || this.attr("data-value"));

    if ($.com.hasValue(value)) {
        value = value.toUpperCase();
        result = value === "TRUE";
    }

    return result;
};

/*
* jQuery 扩展方法, 为一个组件增加/去掉必填验证
* @param { arg } bool 值是否必填
* @returns 返回元素的jQuery对象本身
*/
jQuery.fn.required = function (arg) {
    return this.each(function () {
        var $this = $(this);
        if (arg !== false) {
            $this.attr("required", "required");
            if ($this.parents('.form-group')) {
                $this.parents(".form-group").find(".required").show();
            }
        } else {
            $this.removeAttr("required", "required");
            if ($this.parents('.form-group')) {
                $this.parents(".form-group").find(".required").hide();
            }
        }
    });
};

jQuery.fn.inputSelect = function (arg) {
    var $this = $(this);
    //初始化组件
    if ($.com.hasValue(arg)) {
        var $template = $('#__InputDropDownList').children().clone();
        var $select = $template.find("select.inputSelect");
        var dataSource = arg.dataSource;
        if ($.com.hasValue(dataSource)) {
            if ($.com.isArray(dataSource.data)) {
                $.each(dataSource.data, function (i, x) {
                    var option = document.createElement("option");
                    dataSource.textField = dataSource.textField || "Name";
                    dataSource.valueField = dataSource.valueField || "Id";

                    $(option).html(x[dataSource.textField]);
                    $(option).attr("value", x[dataSource.valueField]);

                    if ($.com.hasValue(dataSource.selectValue) && dataSource.selectValue == x[dataSource.valueField]) {
                        $(option).attr("selected", "selected");
                    }

                    $select.append(option);
                });
            }
        }

        $this.replaceWith($template);
        $template.prepend($this);
    } else {
        //返回组件对象值

    }
}

/*
* jQuery 扩展方法, 判断一个元素是否为有值的 jQuery 对象
* @returns bool 返回判断结果
*/
jQuery.fn.hasValue = function () {
    return this.hasOwnProperty('length') && this.length > 0;
};

/*
* jQuery 扩展方法, 判断两个 jQuery 对象是否相等
* @param { el } 任意 jQuery 对象或选择器
* @returns bool 返回判断结果
*/
jQuery.fn.equal = function (el) {
    var $el = $(el);
    var result = false;
    if (this.hasValue() && $el.hasValue() && this.length === $el.length) {
        result = true;
        for (var i = 0; i < this.length; i++) {
            if (this[i] !== $el[i]) {
                result = false;
                break;
            }
        }
    }

    return result;
};

/*
* jQuery 扩展方法, 判断一个元素是否为另一个元素的父级元素
* @param { el } 任意 jQuery 对象或选择器
* @returns bool 返回判断结果
*/
jQuery.fn.isParentOf = function (el) {
    var $el = $(el);
    return !this.equal($el) && $el.closest(this).hasValue();
};

/*
* jQuery 扩展方法, 判断一个元素是否为另一个元素的子级元素
* @param { el } 任意 jQuery 对象或选择器
* @returns bool 返回判断结果
*/
jQuery.fn.isChildOf = function (el) {
    var $el = $(el);
    return !this.equal($el) && this.closest($el).hasValue();
};

/*
* jQuery 扩展方法, 判断一个元素是否属于另一个 form 元素
* @param { el } 任意 jQuery 对象或选择器
* @returns bool 返回判断结果
*/
jQuery.fn.isBelongToForm = function (el) {
    var $el = $(el);
    var $form = this.parents(_config_.selector.form).first();
    var $notForm = this.parents(_config_.selector.notForm).first();
    return $form.equal($el) && (!$notForm.hasValue() || $form.isChildOf($notForm));
};

/*
* jQuery 扩展方法, 从jQuery 对象中移除 el
* @param { el } 任意 jQuery 对象或选择器
* @returns jQuery 返回移除后的对象
*/
jQuery.fn.removeItem = function (el) {
    var $el = $(el);

    if (this.hasValue()) {
        var index = 0;
        for (var i = 0; i < this.length; i++) {
            if (this.eq(i).equal($el)) {
                index = i;
                break;
            }
        }

        this.splice(index, 1);
    }

    return this;
};
